#include "decl.h"
#include "symbol.h"
#include "grammar.h"
#include <string.h>
#include "expr.h"
#include "ast.h"
#include "stmt.h"

#ifndef WIN32
#define _strdup strdup
#endif

#define CHECK_NULL(p) do { \
    if (p == nullptr)      \
        return nullptr;    \
	p->token = tokc;\
	p->loc = tokc.loc;\
} while (0)

#define EXPECT_TOKEN(ptr, token) \
do {\
    if (tokc.kind != token) {\
		delete ptr;\
		ptr = nullptr;\
		return nullptr;\
    }\
	token_next();\
} while (0)

#define	PRINT_DEBUG_INFO(LP_args_RP)\
	do {\
		printf("%s %d:  ", __FILE__,__LINE__);	\
		printf LP_args_RP ;	\
		printf("\n");	\
	} while(0)

typedef_t* g_typedef = nullptr;

static dector_t* parse_dector(int kind);
static specifier_t* parse_decl_specifiers(void);

struct block_stmt_t;

struct block_stmt_t* parse_block_stmt();

int  is_type_name(int tok);

/*  to allow	struct{	; },	empty struct declaration */
static int FIRST_StructDeclaration[]   = { FIRST_DECLARATION, TK_SEMICOLON,0};
static int FF_StructDeclaration[]      = { FIRST_DECLARATION, TK_SEMICOLON,TK_RBRACE, 0};

static int FIRST_Function[]            = { FIRST_DECLARATION, TK_LBRACE, 0};
/* to allow ";" */
static int FIRST_ExternalDeclaration[] = { FIRST_DECLARATION, TK_MUL, TK_LPAREN, TK_SEMICOLON,0};

static tdname_t *TypedefNames, *OverloadNames;

int FIRST_Declaration[] = { FIRST_DECLARATION, 0};


/**
 * Get the identifier declared by the declarator dec
 */
/*	int * a[3][5]		---->   OutermostID is "a" */
static char* get_outermost_id(dector_t* dec)
{
	if (dec->kind == NK_NameDeclarator)
		return dec->id;

	return get_outermost_id(dec->dec);
}

const static char * nodeKindNames[] = {

		"NK_TranslationUnit", 	"NK_Function",		   "NK_Declaration",
		"NK_TypeName",			"NK_Specifiers",		  " NK_Token",				
		"NK_TypedefName", 		"NK_EnumSpecifier",	   "NK_Enumerator",			
		"NK_StructSpecifier", 	"NK_UnionSpecifier",	   "NK_StructDeclaration",	
		"NK_StructDeclarator",	"NK_PointerDeclarator",  "NK_ArrayDeclarator",		
		"NK_FunctionDeclarator",	"NK_ParameterTypeList",  "NK_ParameterDeclaration",
		"NK_NameDeclarator",		"NK_InitDeclarator",	   "NK_Initializer",
		
		"NK_Expression",
	
		"NK_ExpressionStatement", "NK_LabelStatement",	   "NK_CaseStatement",		
		"NK_DefaultStatement",	 "NK_IfStatement", 	   "NK_SwitchStatement",		
		"NK_WhileStatement",		"NK_DoStatement", 	   "NK_ForStatement", 	
		"NK_GotoStatement",		"NK_BreakStatement",	   "NK_ContinueStatement",		
		"NK_ReturnStatement", 	"NK_CompoundStatement"
};

/* for trace */
void print_ast_dector(dector_t* dec){
	if(dec){
		char * id = get_outermost_id(dec);
		if(id){
			PRINT_DEBUG_INFO(("%s", id));
		}
	}
	while (dec){		
		PRINT_DEBUG_INFO(("kind =  %d, %s", dec->kind, nodeKindNames[dec->kind]));
		dec = dec->dec;
	}

}


/**
 * UCC divides the syntax parsing and semantic check into two seperate passes.
 * But during syntax parsing, the parser needs to recognize C's typedef name.
 * In order to handle this, the parser performs minimum semantic check to 
 * process typedef name. For the parser, it is enough to know if an identifier 
 * is a typedef name.
 * 
 * The parser uses struct tdName to manage a typedef name. 
 * id: typedef name id
 * level: if two typedef names' id are same, the level will be the level of the 
 * typedef name who is in the outer scope. e.g.
 * typedef int a;
 * int f(void)
 * {
 *     typedef int a;
 * }
 * the a's level will be 0 instead of 1.
 * overload: A typedef name maybe used as variable in inner scope, e.g.
 * typedef int a;
 * int f(int a)
 * {
 * }
 * In f(), a is used as variable instead of typedef name.
 * For these cases, overload is set. When the scope terminates, overload 
 * is reset.
 *
 * The parser maintains two vectors: TypedefNames and OverloadNames
 * Whenever encountering a declaration, if it is a typedef name, records
 * it in the TypedefNames; else if the declaration redefines a typedef name
 * in outer scope as a variable, records it in the OverloadNames.
 * TypedefNames is for all the scope, while OverloadNames is for current scope,
 * when current scope terminates, reset the overload flags of all the item in
 * OverloadNames.
 */

/**
 * Decide if id is a typedef name
 */
static int IsTypedefName(char *id)
{
	auto v = TypedefNames;
	/**
	 void f(void){
		 typedef struct{
			 int a[4];
		 }Data;
	 }
	 Data dt;		--------------  Even we are parsing here,
	 						'Data' is still in TypedefNames,
	 						But (tn->level) > Level.
	 						So we don't treat dt as a TypedefName.

	 						Data:  tn->level = 1, Level = 0
	 int main(){
		 return 0;
	 }

	 */
	for (int i = 0; i < sv_count(v); ++i) {
		auto tn = v + i;
		if (tn->id == id && tn->level <= g_cur_level && ! tn->overload)
			return 1;
	}

	return 0;
}

/**
 * If sclass is TK_TYPEDEF, records it in TypedefNames.
 * Otherwise, if id redefines a typedef name in outer scope,
 * records the typedef name in OverloadNames.
 */
/*	This function only records TypedefName, not 'Check' as the function name indicates. */
static void CheckTypedefName(int sclass, char *id)
{
	auto v = TypedefNames;
	/**
		void f(int a,int){	----------- illegal in C, but we check it in declchk.c,
									not during syntax parsing.
		}
	 */
	if (id == NULL)
		return;

	v = TypedefNames;
	if (sclass == TK_TYPEDEF)
	{
		/**
			typedef	int	INT_32
			sclass:
					TK_TYPEDEF
			id:	
					INT_32
		 */
		for (int i = 0; i < sv_count(v); ++i) {
			auto tn = v + i;
			if(strcmp(tn->id, id) == 0)
			{
				/**
				(1)
				typedef	const int CINT32;
				void f(int a,int b){
					typedef	const int CINT32;
				}
				
						 Level = 1, tn->level = 0 
				(2)
				void f(int a,int b){
					typedef	const int CINT32;
				}
				typedef	const int CINT32;
				
						Level = 0, tn->level = 1 
				 */
				/* PRINT_DEBUG_INFO(("Level = %d, tn->level = %d ", Level, tn->level)); */
				if (g_cur_level < tn->level)
					tn->level = g_cur_level;
				return;
			}
		}
		/**
			If there isn't a typedefed name , e.g.  "INT_32",
			we insert it into TypedefNames
		 */
		tdname_t td;
		auto tn = &td;
		tn->id = id;
		tn->level = g_cur_level;
		tn->overload = 0;
		sv_push_size((void**)TypedefNames, tn, sizeof(*tn));
	}
	else
	{
		/**
			typedef	int	a;
			int f(int a){
				...>> 'a' is a parameter instead of typedef name in f()'s definition
			}
		 */
		for (int i = 0; i < sv_count(v); ++i) {
			auto tn = v + i;
			if (strcmp(tn->id, id) == 0 && g_cur_level > tn->level)
			{
				tn->overload = 1;
				tn->overloadLevel = g_cur_level;
				sv_push_size((void**)OverloadNames, tn, sizeof(*tn));
				return;
			}
		}
	}
}

/**
 * Perform minimum semantic check for each declaration 
 */
/*
	Anytime, when we have parsed a declaration,
	int * a[3][5], b;	-----> 	'a' is a declarator id, b is also a declarator id.
	we call	PreCheckTypedef(...) for each declaration id in the declaration.
 The real work is done by CheckTypedefName(...)
*/
static void PreCheckTypedef(decl_t* decl)
{
	ast_node_t* p;
	int sclass = 0;
	/*
	 If 'typedef' is in the linked list pointed by stgClasses,
	 it should be the first one .   
	 Only one storage-class-specifier is allowed ?
		see function CheckDeclarationSpecifiers();
	*/
	if (decl->specs->storage_class != NULL)
	{
		sclass = ((ast_token_t*)decl->specs->storage_class)->token.kind;
	}

	p = decl->initDecs;
	/**
		(1) typedef const int CINT_32;		
			is considered as a declaration syntactically.
			
		"typedef":
				storage-class-specifier
		"int":
				type-specifier
		"const":
				type-qualifier
		"CINT_32":
				declarator.

			int this case, the outer most id "CINT_32"  is a typedefed name
		(2) const int CINT_32;
			int this case, the outer most id "CINT_32" is a normal declarator id.
	 */
	while (p != NULL)
	{
		CheckTypedefName(sclass, get_outermost_id(((init_dector_t*)p)->dec));
		p = p->next;
	}
}

static void PrintOverloadNames(void){
	PRINT_DEBUG_INFO(("PrintOverloadNames(void): "));
	for (int i = 0; i < sv_count(OverloadNames); ++i) {
		auto tn = OverloadNames + i;
		PRINT_DEBUG_INFO(("Level %d : tn: id = %s, level = %d,overload = %d, overloadLevel = %d",
			g_cur_level, tn->id, tn->level, tn->overload, tn->overloadLevel));	
	}
}

/**
 * When current scope except file scope terminates, clear OverloadNames.
 */
void PostCheckTypedef(void)
{
	int overloadCount = 0;
	/* PrintOverloadNames(); */
	
	for (int i = 0; i < sv_count(OverloadNames); ++i) {
		auto tn = OverloadNames + i;
		if(g_cur_level <= (tn->overloadLevel)){
			tn->overload = 0;
		}else if(tn->overload  != 0){
			overloadCount++;
		}
	}
		
	/* PrintOverloadNames();		*/
	if(overloadCount == 0){
		sv_free(OverloadNames);
		OverloadNames = nullptr;
	}
}

bool is_typedef(const char* id)
{
	for (int i = 0; i < sv_count(g_typedef); ++i) {
		auto iter = g_typedef + i;
		if (iter->id == id && iter->level <= g_cur_level && !iter->overload)
			return true;
	}
	return false;
}

/**
 *  initializer:
 *		assignment-expression
 *		{ initializer-list }
 *		{ initializer-list , }
 *
 *  initializer-list:
 *		initializer
 *		initializer-list, initializer
 */
/* see the comments near "struct astInitializer" in header file for detail. */
static ast_init_t* parse_initializer(void)
{
	auto init = new ast_init_t;
	CHECK_NULL(init);
	init->kind = NK_Initializer;
	ast_node_t **tail;

	/* { {1,2,3},4,5,6} */
	if (tokc.kind == TK_LBRACE)
	{
		init->lbrace = 1;
		token_next();
		init->initials = parse_initializer();
		tail = &init->initials->next;
		while (tokc.kind == TK_COMMA)
		{
			token_next();
			if (tokc.kind == TK_RBRACE)
				break;
			*tail = parse_initializer();
			tail = &(*tail)->next;
		}
		EXPECT_TOKEN(init, TK_RBRACE);
	}
	else
	{
		init->lbrace = 0;
		init->expr = parse_assign_expression();
	}

	return init;
}

/**
 *  init-declarator:
 *		declarator
 *      declarator = initializer
 */
static init_dector_t* parse_init_dector(void)
{
	auto init = new init_dector_t;
	CHECK_NULL(init);
	init->kind = NK_InitDeclarator;

	init->dec = parse_dector(DEC_CONCRETE);
	if (tokc.kind == TK_ASSIGN)
	{
		token_next();
		init->init = parse_initializer();
	}

	return init;
}

/**
 *  direct-declarator:
 *		ID
 *		( declarator )
 *
 *  direct-abstract-declarator:
 *		( abstract-declarator)
 *		nil
 */
static dector_t* parse_direct_dector(int kind)
{
	dector_t* dec;

	/* see examples/cast/funcCast.c */
	if (tokc.kind == TK_LPAREN)
	{
		make_bak_token_point();
		token_next();
		auto t = tokc.kind;
		if (t != TK_ID && t !=TK_LPAREN && t != TK_MUL){
			/* we are sure that it cant' be the prefix of a  Declarator */
			restore_token_point();
			dec = new dector_t;
			CHECK_NULL(dec);
			dec->kind = NK_NameDeclarator;
		} else {
			restore_token_point();
			token_next();
			dec = parse_dector(kind);
			EXPECT_TOKEN(dec, TK_RPAREN);
		}
		return dec;
	}

	dec = new dector_t;
	CHECK_NULL(dec);
	dec->kind = NK_NameDeclarator;

	if (tokc.kind == TK_ID)
	{
		if (kind == DEC_ABSTRACT)
		{
			do_error(&tokc.loc, "Identifier is not permitted in the abstract declarator");
		}		
		dec->id = new_auto_str(&tokc);
		/* PRINT_DEBUG_INFO(("dec->id :%s ",dec->id)); */
		token_next();
	}
	else if (kind == DEC_CONCRETE)
	{
		do_error(&tokc.loc, "Expect identifier");
	}

	return dec;
}

/**
 *  parameter-declaration:
 *		declaration-specifiers declarator
 *		declaration-specifiers abstract-declarator
 */
/*  one declaration, such as "int a "  in 	"f(int a, int b, int c)" */
static param_decl_t* parse_parameter_decl(void)
{
	auto paramDecl = new param_decl_t;
	CHECK_NULL(paramDecl);
	paramDecl->kind = NK_ParameterDeclaration;

	paramDecl->specs = parse_decl_specifiers();
	/*
	 f(int a, int b, int c);	--->  CONCRETE
	 or
	 f(int, int , int)		--->	ABSTRACT
	*/
	/**
		Here is Declarator in f(int a,int b, int c), not InitDeclarator.
		Because in C,
			f(int a = 3, int b = 5, int c = 6) is illegal.
	 */
	paramDecl->dec   = parse_dector(DEC_ABSTRACT | DEC_CONCRETE);

	return paramDecl;
}

/**
 *  parameter-type-list:
 *		parameter-list
 *		parameter-list , ...
 *
 *  parameter-list:
 *		parameter-declaration
 *		parameter-list , parameter-declaration
 *
 *  parameter-declaration:
 *		declaration-specifiers declarator
 *		declaration-specifiers abstract-declarator
 */
 /**

		"int a, int b, int c "  in 	f(int a , int b , int c )
		or
		"int,int,int" in g(int,int,int)
  */
ast_param_type_list_t* ParseParameterTypeList(void)
{
	auto paramTyList = new ast_param_type_list_t;
	CHECK_NULL(paramTyList);
	paramTyList->kind = NK_ParameterTypeList;
	ast_node_t* *tail;

	paramTyList->param_decls = parse_parameter_decl();
	tail = &paramTyList->param_decls->next;
	while (tokc.kind == TK_COMMA)
	{
		token_next();
		if (tokc.kind == TK_ELLIPSIS)
		{
			paramTyList->ellipsis = 1;
			token_next();
			break;
		}
		*tail = parse_parameter_decl();
		tail = &(*tail)->next;
	}

	return paramTyList;
}

/**
 *  postfix-declarator:
 *		direct-declarator
 *		postfix-declarator [ [constant-expression] ]
 *		postfix-declarator ( parameter-type-list)
 *		postfix-declarator ( [identifier-list] )
 *
 *  postfix-abstract-declarator:
 *		direct-abstract-declarator
 *		postfix-abstract-declarator ( [parameter-type-list] )
 *		postfix-abstract-declarator [ [constant-expression] ]
 */
/**
	int arr[3];	
	int (arr)[3];
	int (*)[3] arr;		----	error		

	int typedef (* ARR)[3] ;		---> right from syntactic view, but not normal case
	typedef int (* ARR)[3] ;
			typedef a new type, name it ARR.
	int (*arr)[3];		arr is a pointer variable, which points an array of 3 ints

	
	direct-declarator:
			arr
 */
static dector_t* parse_postfix_dector(int kind)
{
	dector_t* dec = parse_direct_dector(kind);

	while (1)
	{
		if (tokc.kind == TK_LBRACKET)
		{
			auto arrDec = new array_dector_t;
			CHECK_NULL(arrDec);
			arrDec->kind = NK_ArrayDeclarator;
			arrDec->dec = dec;
			token_next();
			if (tokc.kind != TK_RBRACKET)
			{
				arrDec->expr = parse_constant_expression();
			}
			EXPECT_TOKEN(arrDec, TK_RBRACKET);

			dec = (dector_t*)arrDec;
		}
		else if (tokc.kind == TK_LPAREN)
		{
			/*
			 notice: for abstract declarator, identifier list is not permitted,
			 but we leave this to semantic check
			*/
			auto funcDec = new fn_dector_t;
			CHECK_NULL(funcDec);
			funcDec->kind = NK_FunctionDeclarator;
			funcDec->dec = dec;
			
			token_next();
			if (is_type_name(tokc.kind))
			{
				/**
					f(int a, int b, int c);
				 */
				funcDec->paramTyList = ParseParameterTypeList();
			}
			else
			{
				if (tokc.kind == TK_ID)	
				{
					/**
						f(a,b,c);
							a	,b	,c
					 */
					svs_push_ptr(funcDec->ids, ref_to_mstring(&tokc.ss));

					token_next();
					while (tokc.kind == TK_COMMA)
					{
						token_next();
						if (tokc.kind == TK_ID)
						{
							svs_push_ptr(funcDec->ids, ref_to_mstring(&tokc.ss));
						}
						EXPECT_TOKEN(funcDec, TK_ID);
					}
				}
			}
			EXPECT_TOKEN(funcDec, TK_RPAREN);
			dec = (dector_t*)funcDec;
		}
		else
		{
			return dec;
		}
	}
}

/**
 *  abstract-declarator:
 *		pointer
 *		[pointer] direct-abstract-declarator
 *
 *  direct-abstract-declarator:
 *		( abstract-declarator )
 *		[direct-abstract-declarator] [ [constant-expression] ]
 *		[direct-abstract-declarator] ( [parameter-type-list] )
 *
 *  declarator:
 *		pointer declarator
 *		direct-declarator
 *
 *  direct-declarator:
 *		ID
 *		( declarator )
 *		direct-declarator [ [constant-expression] ]
 *		direct-declarator ( parameter-type-list )
 *		direct-declarator ( [identifier-list] )
 *
 *  pointer:
 *		* [type-qualifier-list]
 *		* [type-qualifier-list] pointer
 *
 *  We change the above standard grammar into more suitable form defined below.
 *  abstract-declarator:
 *		* [type-qualifer-list] abstract-declarator
 *		postfix-abstract-declarator
 *	
 *  postfix-abstract-declarator:
 *		direct-abstract-declarator
 *		postfix-abstract-declarator [ [constant-expression] ]
 *		postfix-abstrace-declarator( [parameter-type-list] )
 *		
 *  direct-abstract-declarator:
 *		( abstract-declarator )
 *		NULL
 *
 *  declarator:
 *		* [type-qualifier-list] declarator
 *		postfix-declarator
 *
 *  postfix-declarator:
 *		direct-declarator
 *		postfix-declarator [ [constant-expression] ]
 *		postfix-declarator ( parameter-type-list)
 *		postfix-declarator ( [identifier-list] )
 *
 *  direct-declarator:
 *		ID
 *		( declarator )
 *
 *	The declartor is similar as the abstract declarator, we use one function
 *	parse_declarator() to parse both of them. kind indicate to parse which kind
 *	of declarator. The possible value can be:
 *	DEC_CONCRETE: parse a declarator
 *	DEC_ABSTRACT: parse an abstract declarator
 *	DEC_CONCRETE | DEC_ABSTRACT: both of them are ok
 */
/**
	For function declaration:
		DEC_CONCRETE|DEC_ABSTRACT
	For function definition
		DEC_CONCRETE
	For type-name, 	sizeof(type-name),	 (type-name)(expr)
		DEC_ABSTRACT
 */
static dector_t* parse_dector(int kind)
{
	if (tokc.kind == TK_MUL)
	{
		/*
		 * [type-qualifier-list] declarator
		 *  is TK_MUL
		*/
		auto ptrDec = new ptr_dector_t;
		CHECK_NULL(ptrDec);
		ptrDec->kind = NK_PointerDeclarator;
		ast_token_t* tok;
		ast_node_t* *tail;

		tail = &ptrDec->ty_quals;

		token_next();
		/*	[type-qualifier-list] */
		while (tokc.kind == TK_CONST || tokc.kind == TK_VOLATILE)
		{
			tok = new ast_token_t;
			CHECK_NULL(tok);
			tok->kind = NK_Token;
			*tail = (ast_node_t*)tok;
			tail = &tok->next;
			token_next();
		}
		/* declarator */
		ptrDec->dec = parse_dector(kind);

		return (dector_t*)ptrDec;
	}

	return parse_postfix_dector(kind);
}

/**
 *  declaration-specifiers:
 *		storage-class-specifier [declaration-specifiers]
 *		type-specifier [declaration-specifiers]
 *		type-qualifier [declaration-specifiers]
 *
 *  storage-class-specifier:
 *		auto
 *		register
 *		static
 *		extern
 *		typedef
 *
 *  type-qualifier:
 *		const
 *		volatile
 *
 *  type-specifier:
 *		void
 *		char
 *		short
 *		int
 *		long
 *		float
 *		double
 *		signed
 *		unsigned
 *		struct-or-union-specifier
 *		enum-specifier
 *		typedef-name
 */
static specifier_t* parse_decl_specifiers(void)
{
	specifier_t* specs;
	ast_token_t* tok;
	ast_node_t **scTail, **tqTail, **tsTail;
	bool type_seen = false;

    specs = new specifier_t;
	CHECK_NULL(specs);
	specs->kind = NK_Specifiers;
	/* static , auto, register, ... */
	scTail = &specs->storage_class;
	/* const , volatile */
	tqTail = &specs->type_qulifier;
	/* int, double ,	... */
	tsTail = &specs->type_specifier;
	/**
		The real parsing we do here is :
			declaration-specifiers(opt)
		for example:
			f(void){	--------- when we see f, we return immediately.
			}
		So we must check whether it is legal to miss the declaration-specifiers 
		at later stage.
	 */
next_specifier:
	switch (tokc.kind)
	{
	case TK_AUTO:
	case TK_REGISTER:
	case TK_STATIC:
	case TK_EXTERN:
	case TK_TYPEDEF:
		/* storage-class-specifier */
        tok = new ast_token_t;
        CHECK_NULL(tok);
        tok->kind = NK_Token;
		*scTail = tok;
		scTail = &tok->next;
		token_next();
		break;

	case TK_CONST:
	case TK_VOLATILE:
		/* type-qualifier */
        tok = new ast_token_t;
        CHECK_NULL(tok);
        tok->kind = NK_Token;
		*tqTail = tok;
		tqTail = &tok->next;
		token_next();
		break;

	case TK_VOID:
	case TK_CHAR:
	case TK_SHORT:
	case TK_INT:
	case TK_INT64:
	case TK_LONG:
	case TK_FLOAT:
	case TK_DOUBLE:
	case TK_SIGNED:
	case TK_UNSIGNED:
		/**
			typedef signed int t;
			typedef int plain;
			struct tag {
				const t;	...>>	const signed int;	declare nothing.
				plain r;	...>>	int r;
				unsigned t;	...>>   unsigned int t;
			};
		 */
		/* These basic types are type-specifier */
        tok = new ast_token_t;
        CHECK_NULL(tok);
        tok->kind = NK_Token;
		*tsTail = tok;
		tsTail = &tok->next;
		type_seen = true;
		token_next();
		break;

	case TK_ID:
		/*
			when we meet an id, we should find out whether is a typedefed name.
		  A typedefed name is also treated as type-specifier
		*/
		if (!type_seen && is_typedef(str(&tokc))) {
			auto tname = new ast_typedef_t;
			CHECK_NULL(tname);
			tname->kind = NK_TypedefName;
			tname->id = _strdup(str(&tokc));
			*tsTail = (ast_node_t*)tname;
			tsTail = &tname->next;
			token_next();
			type_seen = true;
			break;
		} 
		return specs;

	case TK_STRUCT:
	case TK_UNION:
		/* struct-or-union-specifier is also considered as type-specifier */
		// *tsTail = (ast_node_t*)ParseStructOrUnionSpecifier();
		tsTail = &(*tsTail)->next;
		type_seen = true;
		break;

	case TK_ENUM:
		/* enum-specifier is considered as type-specifier too. */
		// *tsTail = (ast_node_t*)ParseEnumSpecifier();
		tsTail = &(*tsTail)->next;
		type_seen = true;
		break;

	default:
		return specs;
	}
	goto next_specifier;
}

int is_type_name(int tok)
{
	return tok == TK_ID ? IsTypedefName(ref_to_string(&tokc.ss)) : (tok >= TK_AUTO && tok <= TK_VOID);
}

/**
 * type-name:
 *     specifier-qualifier-list abstract-declarator
 */
/*
 (1) type-name is mainly used for cast-expresion and sizeof(type-name), but not for declaration.
 (2) storage-class-specifier is excluded here, 
*/
ast_type_name_t* parse_type_name(void)
{
	auto tyName = new ast_type_name_t;
	CHECK_NULL(tyName);
	tyName->kind = NK_TypeName;
	tyName->specs = parse_decl_specifiers();
	/*
		when declaring a variable, we allocate memory for it.
	 so we need storage-class-specifier in a declaration to specify where the variable is .
	 However, when it comes to only type information, we just care for the type itself.
	*/
	if (tyName->specs->storage_class != NULL)
	{
		do_error(&tyName->token.loc, "type name should not have storage class");
		tyName->specs->storage_class = NULL;
	}
	tyName->dec = parse_dector(DEC_ABSTRACT);

	return tyName;
}

/**
 *  The function defintion and declaration have some common parts:
 *	declaration-specifiers [init-declarator-list]
 *  if we found that the parts followed by a semicolon, then it is a declaration
 		see ParseDeclaration().
 *  or if the init-declarator list is a stand-alone declarator, then it may be
 *  a function definition.
 */
/*
  "int;" can be seen as  a declaration ? 
  "int a;"
 	parse :		declaration-specifiers [init-declarator-list]
  In fact ,it is not perfectly suitable for function-definition,
  So we need GetFunctionDeclarator() later.
 */
static decl_t* parse_common_header(void)
{
	decl_t *decl;
	ast_node_t **tail;

	decl = new decl_t;
	CHECK_NULL(decl);
	decl->kind = NK_Declaration;
	/* declaration-specifiers */
	decl->specs = parse_decl_specifiers();
	if (tokc.kind != TK_SEMICOLON)
	{
		/*
		 a = 3, b , c=50;
		 or
		 f(int a, int b);	
		 [init-declarator-list]
		*/
		decl->initDecs = parse_init_dector();
		tail = &decl->initDecs->next;
		while (tokc.kind == TK_COMMA)
		{
			token_next();
			*tail = parse_init_dector();
			tail = &(*tail)->next;
		}
	}

	return decl;
}
/**
declaration
	declaration-specifiers [init-declarator-list]
 */
decl_t* parse_decl(void)
{
	decl_t* decl = parse_common_header();
	EXPECT_TOKEN(decl, TK_SEMICOLON);
	PreCheckTypedef(decl);
	return decl;
}

/**
 * If initDec is a legal function declarator, return it 
 */
/*
 Because of the inaccurate processing of ParseCommonHeader(void)  ,
 So we need GetFunctionDeclarator(...) to check whether it's a function-declarator.
*/
static fn_dector_t* get_fn_dector(init_dector_t* initDec)
{
	dector_t* dec;
	/*
	 (1) initDec->next == NULL
			for function-definition, only one astInitDeclarator in the node-list.
			int abc, g(int a,int b) { } 	is illegal.
	 (2) initDec->init == NULL
			for function-definition,
			int g(int a, int b) = 30;		is illegal.
	 That is , function declarator has not sibling node, without  "= {1,2,3}"  either.
	 So , for function declarator:
	 initDec->next is NULL, and  initDec->init is NULL.
	*/
	if (initDec == NULL || initDec->next != NULL || initDec->init != NULL)
		return NULL;

	dec = initDec->dec;
	/**
	see	examples/declaration/complicateDecl.c
		int (* f(void))(void){
			return 0;
		}
		NK_FunctionDeclartor->NK_PointerDeclarator-> NK_FunctionDeclarator->NK_NameDeclarator
	 */
	while (dec ){
		if(dec->kind == NK_FunctionDeclarator 
			&& dec->dec && dec->dec->kind == NK_NameDeclarator){
			break;
		}
		dec = dec->dec;
	}
	return (fn_dector_t*)dec;
}

/**
 *  external-declaration:
 *		function-definition
 *		declaration
 *
 *  function-definition:
 *		declaration-specifiers declarator [declaration-list] compound-statement
 *
 *  declaration:
 *		declaration-specifiers [init-declarator-list] ;
 *
 *  declaration-list:
 *		declaration
 *		declaration-list declaration
 */
ast_node_t* parse_external_decl(void)
{
	decl_t* decl = NULL;
	init_dector_t* initDec = NULL;
	fn_dector_t* fdec;
	while (tokc.kind == TK_SEMICOLON) {
		token_next();
	}
	if (tokc.kind == TK_NONE)
		return nullptr;
	/**
		function-definition:
			declaration-specifiers(opt)	declarator  ....
		declaration:
			delcaration-specifiers(opt)	init-declarator-list(opt)

		ParseCommomHeader parses :
			delcaration-specifiers(opt)	init-declarator-list(opt)

		that is, the prefix of function-definition is treated 
			as declaration.  Of course, this is not accurate, 
			so we need GetFunctionDeclarator(...) to further check whether
			it is a real function declarator.
		The key point here is to avoid looking ahead to distinguish whether
		we are parsing function-definition or external-declaration.
	 */
	decl = parse_common_header();
	initDec = (init_dector_t*)decl->initDecs;
	/**
		see ParseDeclarationSpecifiers(),
			(1) storage class information is stored in astToken object.
			(2) typedef is considered a storage-class-specifier syntactically as static, register, extern ,auto.
			(3) only one storage-class-specifier is allowed
	 */
	if (decl->specs->storage_class != NULL &&
		((ast_token_t*)decl->specs->storage_class)->token.kind == TK_TYPEDEF)
		goto not_func;
	/* further check whether it's a real function declarator ? */
	fdec = get_fn_dector(initDec);
	if (fdec != NULL)
	{
		fn_decl_t* func;
		ast_node_t** tail;
		
		if (tokc.kind == TK_SEMICOLON)
		{
			token_next();
			/**
				If current token is not left brace here, we have encounted just a function 
				declaration, not a definition 
			 */
			if (tokc.kind != TK_LBRACE)
				return decl;

			/* maybe a common error, function definition follows ; */
			do_error(&decl->loc, "maybe you accidently add the ;");
		}
		else if (fdec->paramTyList && tokc.kind != TK_LBRACE)
		{	
			/*		
			 a common error, function declaration loses ;
				;	----> semicolon
			*/
			goto not_func;
		}
		/**
			int f(int a, int a){	----->  we have parsed the left part, that is , function declaration.
											when CurrentToken is TK_LBRACE
											and fdec->paramTyList != NULL
					....
			}
			or
			int k(){			------>  when fdec->paramTyList is NULL.
			}
			or
			int f(a,b,c) 			------>  we are here.
											when fdec->paramTyList is NULL.
			int a,b;double c{
			}
		 */
		func = new fn_decl_t;
		CHECK_NULL(func);
		func->kind = NK_Function;
		/* the function declaration's coord and specs are treated as the whole function's. */
		func->loc = decl->loc;
		func->specs = decl->specs;
		/**
		int ** f(int a, int b);
		 astPointerDeclarator-> astPointerDeclarator ->  astFunctionDeclarator --> astDeclarator
			(dec)									(fdec )
		 */
		func->dec = initDec->dec;
		func->fdec = fdec;
		
		g_cur_level++;
		if (func->fdec->paramTyList)
		{
			/**
				int f(int a, int a){ -----------> we are here
			 */
			auto p = func->fdec->paramTyList->param_decls;

			while (p)
			{
				/**
				typedef int a;
				void f(int a){
					...>> we should record 'a' is overloaded in the function definition.
				}
				 */
				/*  TK_BEGIN is 0,   TK_AUTO is 1, see lex.h */
				CheckTypedefName(0, get_outermost_id(((param_decl_t*)p)->dec));
				p = p->next;
			}
		}
		tail = &func->decls;
		/**
			int f(a,b,c) 			------>  we are here.
											when fdec->paramTyList is NULL.
			int a,b;double c;{
			}
		 */
		while (current_token_in(FIRST_Declaration))
		{
			*tail = parse_decl();
			tail = &(*tail)->next;
		}
		g_cur_level--;

		func->nodes = parse_node();

		return func;
	}

not_func:
	/**
		a = 3.0;		---------- see ParseDeclarationSpecifiers()
		void f(void){
			...>> b = 3;	----------- error
		}
	 */
	if(!decl->specs->storage_class && !decl->specs->type_qulifier && !decl->specs->type_specifier){
		do_warning(&decl->loc,"declaration specifier missing, defaulting to 'int'");
		/* see void CheckDeclarationSpecifiers(decl->specs);for defaulting to 'int' */
	}
	/**
		If we get here,
			we should do the same thing as 
			function ParseDeclaration().
	 */
	EXPECT_TOKEN(decl, TK_SEMICOLON);
	PreCheckTypedef(decl);

	return decl;
}

void do_print_decl(ast_node_t* node);

void print_dector(ast_node_t* node)
{
	assert(node->kind == NK_StructDeclarator
	    || node->kind == NK_PointerDeclarator
	    || node->kind == NK_ArrayDeclarator
	    || node->kind == NK_FunctionDeclarator
	    || node->kind == NK_NameDeclarator
	    || node->kind == NK_InitDeclarator
		);
	auto dector = (dector_t*)node;
	if (dector->id) {
		printf("%s", dector->id);
	}
	if (dector->dec)
		do_print_decl(dector->dec);
}

void do_print_decl(ast_node_t* node)
{
	if (node == nullptr)
		return;
	switch (node->kind) {
	case NK_Declaration: {
		decl_t* decl = (decl_t*)node;
		do_print_decl(decl->specs);
		do_print_decl(decl->initDecs);
		if (decl->initDecs) {
			auto next = decl->initDecs->next;
			while (next) {
				printf(", ");
				do_print_decl(decl->initDecs);
			}
		}
		break;
	}
	case NK_Specifiers: {
		specifier_t* spec = (specifier_t*)node;
		do_print_decl(spec->storage_class);
		do_print_decl(spec->type_qulifier);
		do_print_decl(spec->type_specifier);
		break;
	}
	case NK_PointerDeclarator: {
		auto dector = (ptr_dector_t*)node;
		printf("*");
		auto qual = dector->ty_quals;
		while (qual) {
			do_print_decl(qual);
			qual = qual->next;
		}
		do_print_decl(dector->dec);
		break;
	}
	case NK_ArrayDeclarator: {
		auto dector = (array_dector_t*)node;
		print_dector(dector);
		if (dector->expr) {
			printf("[");
			print_expression_s(dector->expr);
			printf("]");
		}
		break;
	}
	case NK_FunctionDeclarator: {
		auto dector = (fn_dector_t*)node;
		print_dector(dector);
		printf("(");
		if (dector->ids) {
			for (int i = 0; i < sv_count(dector->ids); ++i) {
				if (i != 0) {
					printf(", ");
				}
				printf("%s", dector->ids[i]);
			}
		} else {
			do_print_decl(dector->paramTyList);
		}
		printf(")");
		break;
	}
	case NK_InitDeclarator: {
		auto decl = (init_dector_t*)node;
		print_dector(decl->dec);
		if (decl->init) {
			printf(" = ");
			do_print_decl(decl->init);
		}
		break;
	}
	case NK_ParameterTypeList: {
		auto list = (ast_param_type_list_t*)node;
		auto param_decl = list->param_decls;
		while (param_decl) {
			if (param_decl != list->param_decls) {
				printf(", ");
			}
			do_print_decl(param_decl);
			param_decl = param_decl->next;
		}
		break;
	}
	case NK_ParameterDeclaration: {
		auto decl = (param_decl_t*)node;
		do_print_decl(decl->specs);
		printf(" ");
		do_print_decl(decl->dec);
		break;
	}
	case NK_NameDeclarator: {
		print_dector(node);
		break;
	}
	case NK_Token: {
		ast_token_t* tok = (ast_token_t*)node;
		while (tok) {
			printf("%s ", ref_to_string(&tok->token.ss));
			tok = (ast_token_t*)tok->next;
		}
		break;
	}
	case NK_Function: {
		auto decl = (fn_decl_t*)node;
		do_print_decl(decl->specs);
		do_print_decl(decl->dec);
		//do_print_decl(decl->fdec);
		auto decls = decl->decls;
		while (decls) {
			do_print_decl(decl->decls);
			decls = decls->next;
		}
		auto node = decl->nodes;
		while (node) {
			print_node(node);
			node = node->next;
		}
		break;
	}
	case NK_Initializer: {
		auto decl = (ast_init_t*)node;
		if (decl->lbrace) {
			auto init = decl->initials;
			while (init) {
				do_print_decl(init);
				init = init->next;
			}
		}
		else {
			print_node_s(decl->expr);
		}
		break;
	}
	default: {
        assert(0 && "unexpected decl type");
		break;
	}
	}
}

void print_decl(ast_node_t* node)
{
	do_print_decl(node);
	printf(";\n");
}
